package com.jason.session;

import com.jason.config.BoundSql;
import com.jason.config.Configuration;
import com.jason.config.MapperStatement;
import com.jason.util.GenericTokenParser;
import com.jason.util.ParameterMapping;
import com.jason.util.ParameterMappingTokenHandler;

import java.sql.*;
import java.util.List;

public class SimpleExecutor implements Executor {

    private Connection connection;

    private StatementHandler statementHandler;

    private boolean autoCommit = false;

    public SimpleExecutor() {
        this.statementHandler = new BaseStatementHandler();
    }

    public SimpleExecutor(boolean autoCommit) {
        this.statementHandler = new BaseStatementHandler();
        this.autoCommit = autoCommit;
    }

    @Override
    public <E> List<E> query(Configuration configuration, MapperStatement mapperStatement, Object... params) throws Exception {
        String sql = mapperStatement.getSql();
        BoundSql boundSql = getBoundSql(sql);
        connection = getConnnection(configuration);
        //设置参数值
        PreparedStatement preparedStatement = statementHandler.parameterHand(connection, mapperStatement, boundSql, params);

        //执行查询
        ResultSet resultSet = preparedStatement.executeQuery();
        List<E> list = statementHandler.resultHand(resultSet, mapperStatement);
        closeResultSet(resultSet);
        closeStatement(preparedStatement);
        return list;
    }



    @Override
    public int update(Configuration configuration, MapperStatement mapperStatement, Object... params) throws Exception {
        String sql = mapperStatement.getSql();
        BoundSql boundSql = getBoundSql(sql);
        connection = getConnnection(configuration);
        connection.setAutoCommit(autoCommit);  //设置事务自动提交
        //设置参数值
        PreparedStatement preparedStatement = statementHandler.parameterHand(connection, mapperStatement, boundSql, params);
        int result = preparedStatement.executeUpdate();
        closeStatement(preparedStatement);
        return result;
    }


    @Override
    public void close() throws SQLException {
        if (this.connection != null) {
            this.connection.close();
        }
    }

    private void closeStatement(Statement statement) throws SQLException {
        if (statement != null) {
            statement.close();
        }
    }

    private void closeResultSet(ResultSet rs) throws SQLException {
        if (rs != null) {
            rs.close();
        }
    }

    @Override
    public Connection getConnnection(Configuration configuration) throws SQLException {
        return configuration.getDataSource().getConnection();
    }

    @Override
    public void commit() throws SQLException {
        connection.commit();
    }

    @Override
    public void rollBack() throws SQLException {
        connection.rollback();
    }

    private BoundSql getBoundSql(String sql) {

        ParameterMappingTokenHandler tokenHandler = new ParameterMappingTokenHandler();
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", tokenHandler);
        String parseSql = genericTokenParser.parse(sql);
        List<ParameterMapping> parameterMappings = tokenHandler.getParameterMappings();
        return new BoundSql(parseSql, parameterMappings);
    }
}
